#pragma once

#include <atomic>
#include "lwip/tcp.h"
#include "AcHandler.hpp"

class Async;
class AsyncServer;

class AsyncClient {
public:
    AsyncClient(Async* sync, AsyncServer* server);
    void    delete_instance();
    void    reset();
    void    init(tcp_pcb* pcb);
    void    prepare_close_connection();
    void    try_close_connection();
    bool    connect(ip_addr_t ip, uint16_t port);
    bool    connect(const char* name, uint16_t port);
    void    close(bool now = false);
    size_t  get_send_buffer_size();
    size_t  add(const void* data, size_t size, uint8_t apiflags = TCP_WRITE_FLAG_MORE);
    bool    send();
    size_t  write(const void* data, size_t size, uint8_t apiflags = TCP_WRITE_FLAG_COPY);
    tcp_state   get_connection_state();
    uint16_t    get_MSS();
    uint16_t    get_rx_timeout();
    void        set_rx_timeout_second(uint16_t timeout);
    uint32_t    get_ack_timeout();
    void        set_ack_timeout_ms(uint32_t);
    bool        get_nodelay_state();
    void        set_nodelay(bool nodelay);
    ip_addr_t   get_remote_IP();
    ip_addr_t   get_local_IP();
    uint16_t    get_remote_port();
    uint16_t    get_local_port();
    size_t      ack(size_t len);
    void        set_defer_ack(bool defer);
    void        event_count_sub();
    void        event_count_add();

    void    set_connected_event_handler(AcConnectHandler cb, void* arg = nullptr);
    void    set_disconnected_event_handler(AcConnectHandler cb, void* arg = nullptr);
    void    set_ack_event_handler(AcAckHandler cb, void* arg = nullptr);
    void    set_error_event_handler(AcErrorHandler cb, void* arg = nullptr);
    void    set_data_received_handler(AcDataHandler cb, void* arg = nullptr);
    void    set_raw_packet_received_handler(AcPacketHandler cb, void* arg = nullptr);
    void    set_timeout_event_handler(AcTimeoutHandler cb, void* arg = nullptr);
    void    set_poll_event_handler(AcConnectHandler cb, void* arg = nullptr) ;
    err_t   handle_received_event(tcp_pcb* pcb, pbuf* pb, err_t err);
    err_t   handle_connected_event(tcp_pcb* pcb, err_t err);
    err_t   handle_FIN_event(tcp_pcb* pcb, err_t err);
    void    handle_error_event(err_t err);
    err_t   handle_sent_event(tcp_pcb* pcb, uint16_t len);
    err_t   handle_poll_event(tcp_pcb* pcb);
    void    handle_DNS_found_event(ip_addr_t* ipaddr);

    AsyncClient  &operator=(const AsyncClient &other);
    AsyncClient  &operator+=(const AsyncClient &other);
    bool operator==(const AsyncClient &other)
    {
        return m_pcb == other.m_pcb;
    }
    bool operator!=(const AsyncClient &other)
    {
        return !(*this == other);
    }

    AsyncClient* prev;
    AsyncClient* next;
private:
    ~AsyncClient();

    err_t create_recv_event(void *arg, tcp_pcb *pcb, pbuf *pb, err_t err);
    err_t create_sent_event(void* arg, tcp_pcb* pcb, uint16_t len);
    void  create_error_event(void* arg, err_t err);
    err_t create_poll_event(void* arg, tcp_pcb* pcb);
    err_t create_connected_event(void* arg, tcp_pcb* pcb, err_t err);
    void  create_DNS_found_event(const char* name, const ip_addr_t* addr, void* arg);
    void  notify_lwip_data_processed(tcp_pcb* pcb, uint16_t len);

    bool                    m_connect_later;        // 是否延迟连接（等待DNS解析）
    std::atomic<bool>       m_connection_is_err;    // 连接是否错误
    tcp_pcb*                m_pcb;                  // 关联的连接（协议控制块）
    std::atomic<bool>       m_active;               // 当前客户端活跃情况（活跃状况下支持产生事件）
    std::atomic<uint8_t>    m_event_count;          // 当前未处理事件数量
    Async*                  m_async;                // 关联的异步事件处理程序
    AsyncServer*            m_server;               // 关联的服务器（作为客户端使用时无效）
    bool                    m_tx_in_progress;       // 数据正在发送中
    uint32_t                m_last_tx_timestamp;    // 最后发送的时间戳
    bool                    m_defer_ack;            // 是否延迟发送ACK
    size_t                  m_unack_rx_bytes;       // 尚未确认的字节数
    uint32_t                m_last_rx_timestamp;    // 最后接收的时间戳
    uint32_t                m_ack_timeout_ms;       // ACK超时时间限制
    uint16_t                m_rx_timeout_second;    // 接收超时时间限制
    uint16_t                m_remote_port;          // 连接的远端端口

    AcConnectHandler    on_connected_handler;       // 连接成功回调函数
    void*               on_connected_arg;           // 连接成功时传递给回调的参数
    AcConnectHandler    on_disconnected_handler;    // 连接断开回调函数
    void*               on_disconnected_arg;        //
    AcAckHandler        on_data_sent_handler;       // 数据发送完成回调函数
    void*               on_data_sent_arg;           //
    AcErrorHandler      on_error_handler;           // 错误事件回调
    void*               on_error_arg;               //
    AcDataHandler       on_data_received_handler;   // 数据接收回调
    void*               on_data_received_arg;       //
    AcPacketHandler     on_raw_packet_handler;      // 原始数据接收回调
    void*               on_raw_packet_arg;          //
    AcTimeoutHandler    m_timeout_handler;          // 超时事件回调
    void*               m_timeout_arg;              //
    AcConnectHandler    m_poll_handler;             // 轮询事件回调
    void*               m_poll_arg;                 //
};